-
Notifications
You must be signed in to change notification settings - Fork 7
Better scoping of things #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better scoping of things #24
Conversation
1. Move dependency on setuptools closer to where it's needed 2. Scope multiprocessing Pool so a pool left open doesn't hang the process 3. Move run_setup_py to its own file so the subprocess doesn't need to import much
|
This (together with colcon/colcon-ros#86) fails to build a ROS 2 workspace for me: |
|
How does this always re-instantiated multiprocessing pool perform compared to a plain subprocess invocation in terms of runtime? |
|
Significant, but not crazy. It's 4x slower than spawning a Python interpreter in a new process, but if you reuse the process pool, it's 7x faster.
import subprocess
import multiprocessing
import gc
from timeit import timeit
def f0(): return True
def f1(): subprocess.call(['true'])
def f2(): subprocess.call(['python3', '-c', 'True'])
def f3():
with multiprocessing.Pool(1) as pool: pool.apply(f1)
def f4(p): p.apply(f1)
setup = 'gc.enable()'
n=100
print('call', timeit('f0()', setup, number=n, globals=globals())/n)
print('subprocess', timeit('f1()', setup, number=n, globals=globals())/n)
print('interpreter', timeit('f2()', setup, number=n, globals=globals())/n)
print('transient pool', timeit('f3()', setup, number=n, globals=globals())/n)
with multiprocessing.Pool(1) as pool:
print('shared pool', timeit('f4(pool)', setup, number=n,
globals=globals())/n) |
Since the patch currently doesn't reuse the process pool how about keep using subprocess as it is right now in the target branch? |
|
What like about the process pool is it handles return values and exceptions. Plus passing in a process pool can speed up this code as well as the Python project build code. I think it’s worth it to keep using ProcessPool, even if it is a bit slower for now. Premature optimization and whatnot. |
Can you describe how you think the process pool can be used in the future?
This isn't premature optimization. The target branch uses subprocess and the proposed change switches it to a one-time process pool which is a regression in performance (I might need to measure how much it changes). So at the moment using the process pool provides only some convenience advantage which isn't a good argument for the performance impact (assuming it is not insignificant). |
Sure. Passing in a process pool to PythonBuildTask and PythonTestTask prevents the need to spin up a process and (more significantly) the Python interpreter for each invocation. This could be created in the context and persisted for the entire run of colcon.
How noticeable is the change in performance?
I need to redo these tests. I'm not sure they captured the intended code path |
|
I compared the timing of |
|
After one last fix (see prev commit), I'm ready to merge this. |
|
The target branch of this PR only existed while we worked on different approaches to get the information from Python setup files. In the meantime #30 has been merged so I don't see how the current patch can be applied anymore. Therefore I will go ahead and close this ticket. If necessary please consider creating a new pull request targeting |
|
Good move. I support closing this PR. |
I think it would be nice for colcon to pass in a ProcessPoolExecutor that has a longer life, so we don't need to spin one up so often (the expensive part).